package com.jadesoft.common.web.impl;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.PropertyFilter;
import oracle.sql.TIMESTAMP;

import com.jadesoft.common.util.Invisable;
import com.jadesoft.common.web.AjaxAction;
import com.jadesoft.common.web.IResponseRenderer;
import com.jadesoft.common.web.RequestContext;
import com.ufida.leaf.exception.BusinessException;

public class JSONResponseRenderer implements IResponseRenderer {
	private static  final JsonConfig JSON_CONFIG = new JsonConfig();
	
	//如果属性声明称Invisable.class,则该属性不转成JSON
	private static PropertyFilter jsonPropertyFilter = new PropertyFilter() {
		public boolean apply(Object source, String propery, Object value) {
			try {
				Class clz = source.getClass();         
				Field field = source.getClass().getDeclaredField(propery);//class.getField() 只能拿到public属性
				return field.isAnnotationPresent(Invisable.class);
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				return false;//Map,JsonObject return false
//				e.printStackTrace();
			}
			return false;
		}
	};
	
	static {
		JSON_CONFIG.setJsonPropertyFilter(jsonPropertyFilter);
		JsonValueProcessor date_processor = new JsonValueProcessor() {
			public Object processArrayValue(Object obj, JsonConfig jsonconfig) {
				return null;
			}

			public Object processObjectValue(String s, Object obj,
					JsonConfig jsonconfig) {
				return obj == null ? null : new SimpleDateFormat("yyyy-MM-dd")
						.format((Date) obj);
			}
		};
		JSON_CONFIG.registerJsonValueProcessor(Date.class, date_processor);

		JSON_CONFIG.registerJsonValueProcessor(Timestamp.class,
				new JsonValueProcessor() {
					public Object processArrayValue(Object arg0, JsonConfig arg1) {
						return null;
					}

					public Object processObjectValue(String arg0, Object arg1,
							JsonConfig arg2) {
						try {
							return arg1 == null ? null : new SimpleDateFormat(
									"yyyy-MM-dd hh:mm:ss.S")
									.format((Timestamp) arg1);
						} catch (Exception e) {
							throw new BusinessException(e);
						}
					}
				});

		JSON_CONFIG.registerJsonValueProcessor(TIMESTAMP.class,
				new JsonValueProcessor() {
					public Object processArrayValue(Object arg0, JsonConfig arg1) {
						return null;
					}

					public Object processObjectValue(String arg0, Object arg1,
							JsonConfig arg2) {
						try {
							return arg1 == null ? null : new SimpleDateFormat(
									"yyyy-MM-dd").format(((TIMESTAMP) arg1)
									.dateValue());
						} catch (SQLException e) {
							throw new BusinessException(e);
						}
					}
				});
		
		//DOUBLE 格式化为 11.00
		JSON_CONFIG.registerJsonValueProcessor(Double.class,
				new JsonValueProcessor() {
					public Object processArrayValue(Object arg0, JsonConfig arg1) {
						return null;
					}

					public Object processObjectValue(String arg0, Object arg1,
							JsonConfig arg2) {
							if(arg1 == null){
								return null;
							}else{
								String str = arg1.toString();
								if((str.length() - str.indexOf(".")) == 2)
									str += "0";
								return str;
							}
					}
				});
	}

	public void render(HttpServletResponse response, Object data,
			boolean isSuccess) {
		response.setCharacterEncoding("utf-8");
		if (isSuccess) {
			if(response.containsHeader(AjaxAction.JUST_RENDER_RESULT)){
				render(JSONArray.fromObject(data, JSON_CONFIG).toString());
			}else{
				Map<String, Object> json = new HashMap<String, Object>();
				RequestContext context = RequestContext.get();
				json.put("success", context.isSuccess());
				json.put("message", context.getMessage());
				json.put("result", data);
				render(JSONObject.fromObject(json, JSON_CONFIG).toString());
			}
		} else {
			Map<String, Object> json = new HashMap<String, Object>();
			json.put("success", false);
			if(data instanceof InvocationTargetException){
				json.put("exception", ((Exception) data).getCause().getClass()
						.getName());
				json.put("message", ((Exception) data).getCause().getMessage());
			}else{
				json.put("exception", ((Exception) data).getClass()
						.getName());
				json.put("message", ((Exception) data).getMessage());
			}
			
			render(JSONObject.fromObject(json, JSON_CONFIG).toString());
		}
	}

	protected void render(String text) {
		try {
			ServletResponse response = RequestContext.get().getResponse();
			response.getWriter().write(text);
			response.flushBuffer();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
